package com.net.xpay.core.manager.impl;

import com.google.common.base.Preconditions;
import com.google.common.base.Strings;
import com.net.xpay.common.enums.invoice.OpenInvoiceStatus;
import com.net.common.annotation.ReadTransactional;
import com.net.common.annotation.WriteTransactional;
import com.net.common.dao.BasicMapper;
import com.net.common.dao.Page;
import com.net.common.manager.AbstractManager;
import com.net.noah.core.service.SerialNumberService;
import com.net.xpay.core.dao.ChargeRecordMapper;
import com.net.xpay.core.domain.ChargeRecord;
import com.net.xpay.core.enums.PayStatus;
import com.net.xpay.core.manager.ChargeRecordManager;
import com.net.xpay.core.model.ChargeRecordSearchModel;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Propagation;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;


@Component
@ReadTransactional
public class ChargeRecordManagerImpl extends AbstractManager<ChargeRecord> implements ChargeRecordManager{

    @Autowired
    private ChargeRecordMapper mapper;

    @Autowired
    private SerialNumberService serialNumberService;

    @Override
    @WriteTransactional(propagation = Propagation.SUPPORTS)
    public int save(ChargeRecord obj) {
        Preconditions.checkArgument(obj.getId() == null);
        obj.setId(serialNumberService.getLongSerialNumber(getTableFullName()));
        obj.setOutBizNo(obj.getUserId() + "_" + obj.getId());
        return super.save(obj);
    }

    @Override
    protected BasicMapper<Long, ChargeRecord> getMapper() {
        return mapper;
    }

    @Override
    public List<ChargeRecord> listByStatus(PayStatus status) {
        Preconditions.checkArgument(status != null);
        ChargeRecord condition = new ChargeRecord();
        condition.setPayStatus(status);
        return listByCondition(condition, new ArrayList<>());
    }

    @Override
    public List<ChargeRecord> search(ChargeRecordSearchModel searchModel) {
        Preconditions.checkArgument(searchModel != null);
        Page page = new Page(searchModel);
        page.addOrder("id", "desc");
        return mapper.search(searchModel, page);
    }

    @Override
    public long searchCount(ChargeRecordSearchModel searchModel) {
        Preconditions.checkArgument(searchModel != null);
        return mapper.searchCount(searchModel);
    }

    @Override
    public long statChargeAmount(LocalDateTime minEndTime, LocalDateTime maxEndTime, Integer positive) {
        Preconditions.checkArgument(minEndTime != null && maxEndTime != null);
        return mapper.statChargeAmount(minEndTime, maxEndTime, positive);
    }

    @Override
    public long statAmountByAlipayAppQrcode(LocalDateTime minEndTime, LocalDateTime maxEndTime) {
        Preconditions.checkArgument(minEndTime != null && maxEndTime != null);
        return mapper.statAmountByAlipayAppQrcode(minEndTime, maxEndTime);
    }

    @Override
    public long statUserAmountByAlipayAppQrcode(Long userId, LocalDateTime minEndTime, LocalDateTime maxEndTime) {
        Preconditions.checkArgument(userId != null && minEndTime != null && maxEndTime != null);
        return mapper.statUserAmountByAlipayAppQrcode(userId, minEndTime, maxEndTime);
    }

    @Override
    public List<ChargeRecord> list(ChargeRecordSearchModel searchModel) {
        Preconditions.checkArgument(searchModel != null);
        return nonEmptyList(mapper.list(searchModel));
    }

    @Override
    public ChargeRecord findLastPaid(Long userId) {
        Preconditions.checkArgument(userId != null);

        return mapper.findLastPaid(userId);
    }

    @Override
    public ChargeRecord getByOutBizNo(String outBizNo) {
        Preconditions.checkArgument(!Strings.isNullOrEmpty(outBizNo));
        ChargeRecord condition = new ChargeRecord();
        condition.setOutBizNo(outBizNo);
        return getByCondition(condition);
    }

    @Override
    public Long statWaitInvoicingAmount(Long userId, LocalDateTime startTime) {
        Preconditions.checkArgument(userId != null && startTime != null);
        return mapper.statWaitInvoicingAmount(userId, startTime);
    }

    @Override
    public ChargeRecord findById(Long userId, Long id) {
        Preconditions.checkArgument(userId != null && id != null);
        ChargeRecord condition = new ChargeRecord();
        condition.setUserId(userId);
        condition.setId(id);
        return getByCondition(condition);
    }

    @Override
    public int updateOpenInvoiceStatusByIds(List<Long> ids, OpenInvoiceStatus status) {
        Preconditions.checkArgument(ids != null && status != null);
        return mapper.updateOpenInvoiceStatusByIds(ids, status);
    }

    @Override
    public List<ChargeRecord> listByIds(List<Long> ids) {
        Preconditions.checkArgument(ids != null);
        return nonEmptyList(mapper.listByIds(ids));
    }

    @Override
    public ChargeRecord findByImportBizNo(Long userId, String importBizNo) {
        Preconditions.checkArgument(userId != null && !Strings.isNullOrEmpty(importBizNo));
        ChargeRecord condition = new ChargeRecord();
        condition.setUserId(userId);
        condition.setImportBizNo(importBizNo);
        return getByCondition(condition);
    }

    @Override
    public long sumServiceChargeFeeByDay(Long partnerId, LocalDateTime minEndTime, LocalDateTime maxEndTime) {
        Preconditions.checkArgument(partnerId != null && minEndTime != null && maxEndTime != null);
        return mapper.sumServiceChargeFeeByDay(partnerId, minEndTime, maxEndTime);
    }

    @Override
    public long sumUserServiceChargeFeeByDay(Long userId, LocalDateTime minEndTime, LocalDateTime maxEndTime) {
        Preconditions.checkArgument(userId != null && minEndTime != null && maxEndTime != null);
        return mapper.sumUserServiceChargeFeeByDay(userId, minEndTime, maxEndTime);
    }

    @Override
    public long sumCompanyServiceChargeFeeByDay(LocalDateTime minEndTime, LocalDateTime maxEndTime) {
        return mapper.sumCompanyServiceChargeFeeByDay(minEndTime, maxEndTime);
    }
}
